package com.ls.task.listener;

import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.lang3.StringUtils;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.JobListener;
import org.quartz.SchedulerException;
import org.quartz.SchedulerListener;
import org.quartz.Trigger;
import org.quartz.Trigger.CompletedExecutionInstruction;
import org.quartz.TriggerKey;
import org.quartz.TriggerListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import com.alibaba.fastjson.JSON;
import com.ls.task.biz.SysTaskBiz;
import com.ls.task.biz.SysTaskTriggerBiz;
import com.ls.task.dal.model.SysTask;
import com.ls.task.dal.model.SysTaskFire;
import com.ls.task.dal.model.SysTaskTrigger;
import com.ls.task.dal.service.SysTaskFireService;
import com.ls.task.dal.service.SysTaskService;
import com.ls.task.dal.service.SysTaskTriggerService;
import com.ls.task.utils.TaskUtils;

public class SpringListener implements InitializingBean, ApplicationListener<ContextRefreshedEvent>{
	
	protected Logger logger = LoggerFactory.getLogger(getClass());
	
	
	@Autowired
	private SysTaskTriggerBiz sysTaskTriggerBiz;
	@Autowired
	private SysTaskService sysTaskService;
	@Autowired
	private SysTaskTriggerService sysTaskTriggerService;
	@Autowired
	private SysTaskFireService sysTaskFireService;

	@Autowired
	private SchedulerFactoryBean  quertzManager;
	@Autowired
	private SysTaskBiz sysTaskBiz;
	
	private ExecutorService pool = Executors.newCachedThreadPool();

	@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		//需要执行的逻辑代码，当spring容器初始化完成后就会执行该方法。
		if(event.getApplicationContext().getParent() == null){//root application context 没有parent
			
			initScheduler();
			pool.submit(new Callable<String>() {
				@Override
				public String call() throws Exception {
					sysTaskBiz.loadTask();
					sysTaskTriggerBiz.load();
					return null;
				}
			});
		} 
	}

	private void initScheduler() {
		System.out.println("##########开始注册任务事件！");
		try {
			quertzManager.getScheduler().getListenerManager()
			.addJobListener(new JobListener() {
				
				@Override
				public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
					// TODO Auto-generated method stub
					System.out.println("--jobWasExecuted");
				}
				
				@Override
				public void jobToBeExecuted(JobExecutionContext context) {
					// TODO Auto-generated method stub

					System.out.println("--jobToBeExecuted");
				}
				
				@Override
				public void jobExecutionVetoed(JobExecutionContext context) {
					// TODO Auto-generated method stub

					System.out.println("--jobExecutionVetoed");
				}
				
				@Override
				public String getName() {
					return "task listener";
				}
			});
		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		try {
			quertzManager.getScheduler().getListenerManager()
			.addSchedulerListener(new SchedulerListener() {
				
				@Override
				public void triggersResumed(String triggerGroup) {
					// TODO Auto-generated method stub
					System.out.println("--triggersResumed");
				}
				
				@Override
				public void triggersPaused(String triggerGroup) {
					// TODO Auto-generated method stub
					System.out.println("--triggersPaused");
				}
				
				@Override
				public void triggerResumed(TriggerKey triggerKey) {
					// TODO Auto-generated method stub
					System.out.println("--triggerResumed");
				}
				
				@Override
				public void triggerPaused(TriggerKey triggerKey) {
					// TODO Auto-generated method stub
					System.out.println("--triggerPaused");
				}
				
				@Override
				public void triggerFinalized(Trigger trigger) {
					// TODO Auto-generated method stub
					System.out.println("--triggerFinalized");
				}
				
				@Override
				public void schedulingDataCleared() {
					// TODO Auto-generated method stub
					System.out.println("--jobExecutionVetoed");
				}
				
				@Override
				public void schedulerStarting() {
					// TODO Auto-generated method stub
					System.out.println("--schedulerStarting");
				}
				
				@Override
				public void schedulerStarted() {
					// TODO Auto-generated method stub
					System.out.println("--schedulerStarted");
				}
				
				@Override
				public void schedulerShuttingdown() {
					// TODO Auto-generated method stub
					System.out.println("--schedulerShuttingdown");
				}
				
				@Override
				public void schedulerShutdown() {
					// TODO Auto-generated method stub
					System.out.println("--schedulerShutdown");
				}
				
				@Override
				public void schedulerInStandbyMode() {
					// TODO Auto-generated method stub
					System.out.println("--schedulerInStandbyMode");
				}
				
				@Override
				public void schedulerError(String msg, SchedulerException cause) {
					// TODO Auto-generated method stub
					System.out.println("--schedulerError:"+msg);
				}
				
				@Override
				public void jobsResumed(String jobGroup) {
					// TODO Auto-generated method stub
					System.out.println("--jobExecutionVetoed");
				}
				
				@Override
				public void jobsPaused(String jobGroup) {
					// TODO Auto-generated method stub
					System.out.println("--jobsPaused");
				}
				
				@Override
				public void jobUnscheduled(TriggerKey triggerKey) {
					// TODO Auto-generated method stub
					System.out.println("--jobUnscheduled");
				}
				
				@Override
				public void jobScheduled(Trigger trigger) {
					// TODO Auto-generated method stub
					System.out.println("--jobScheduled");
				}
				
				@Override
				public void jobResumed(JobKey jobKey) {
					// TODO Auto-generated method stub
					System.out.println("--jobResumed");
					String[] str = StringUtils.split(jobKey.getName(),"#");
					if(str != null){
						Long  taskId = Long.parseLong(str[0]);
						SysTask model = new SysTask();
						model.setId(taskId);
						model.setStatusCode("resumed");
						sysTaskService.update(model );
					}
				}
				
				@Override
				public void jobPaused(JobKey jobKey) {
					// TODO Auto-generated method stub
					System.out.println("--jobPaused");

					String[] str = StringUtils.split(jobKey.getName(),"#");
					if(str != null){
						Long  taskId = Long.parseLong(str[0]);
						SysTask model = new SysTask();
						model.setId(taskId);
						model.setStatusCode("paused");
						sysTaskService.update(model );
					}
				}
				
				@Override
				public void jobDeleted(JobKey jobKey) {
					// TODO Auto-generated method stub
					System.out.println("--jobDeleted");
					String[] str = StringUtils.split(jobKey.getName(),"#");
					if(str != null){
						Long  taskId = Long.parseLong(str[0]);
						SysTask model = new SysTask();
						model.setId(taskId);
						model.setStatusCode("deleted");
						sysTaskService.update(model );
					}
				}
				
				@Override
				public void jobAdded(JobDetail jobDetail) {
					// TODO Auto-generated method stub
					System.out.println("--jobAdded");
					JobDataMap map = jobDetail.getJobDataMap();
					if(map != null){
						Long  taskId = map.getLongValue(TaskUtils.TASK_ID);
						SysTask model = new SysTask();
						model.setId(taskId);
						model.setStatusCode("added");
						sysTaskService.update(model );
					}
				}
			});
		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			quertzManager.getScheduler().getListenerManager()
			.addTriggerListener(new TriggerListener() {
				
				@Override
				public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
					System.out.println("--vetoJobExecution");
					return false;
				}
				
				@Override
				public void triggerMisfired(Trigger trigger) {
					// TODO Auto-generated method stub
					System.out.println("--triggerMisfired");
				}
				
				@Override
				public void triggerFired(Trigger trigger, JobExecutionContext context) {
					// TODO Auto-generated method stub
					System.out.println("--triggerFired");
					JobDataMap map = context.getMergedJobDataMap();
					if(map != null){
						Long  taskId = map.getLongValue(TaskUtils.TASK_ID);
						Long  triggerId = null;
						if(map.containsKey(TaskUtils.TRIGGER_ID)){
							triggerId = map.getLongValue(TaskUtils.TRIGGER_ID);
						}
						if(taskId != null){
							SysTaskTrigger model = new SysTaskTrigger();
							model.setId(triggerId);
							model.setPreviousDt(context.getPreviousFireTime());
							model.setNextDt(context.getNextFireTime());
							model.setFireDt(context.getFireTime());
							model.setScheduledFireDt(context.getScheduledFireTime());
							model.setStatusCode("fired");
							model.setDoDt(new Date());
							sysTaskTriggerService.update(model );
							SysTaskFire fire = new SysTaskFire();
							fire.setTaskId(taskId);
							fire.setTriggerId(triggerId);
							fire.setPreviousDt(context.getPreviousFireTime());
							fire.setNextDt(context.getNextFireTime());
							fire.setFireDt(context.getFireTime());
							fire.setScheduledFireDt(context.getScheduledFireTime());
							fire.setRunTime(context.getJobRunTime());
							fire.setDoDt(new Date());
							fire.setStatusCode("doing");
							fire.setId(null);
							sysTaskFireService.save(fire );
							context.getMergedJobDataMap().putAsString("fireId", fire.getId());
						}
					}
				}
				
				@Override
				public void triggerComplete(Trigger trigger, JobExecutionContext context,
						CompletedExecutionInstruction triggerInstructionCode) {
					// TODO Auto-generated method stub
					System.out.println("--triggerComplete:"+JSON.toJSONString(context.getMergedJobDataMap()));
					System.out.println("--triggerComplete:"+context.getResult());
					JobDataMap map = context.getMergedJobDataMap();
					if(map != null){
						Long  taskId = map.getLongValue(TaskUtils.TASK_ID);
						Long  triggerId = null;
						if(map.containsKey(TaskUtils.TRIGGER_ID)){
							triggerId = map.getLongValue(TaskUtils.TRIGGER_ID);
						}
						if(taskId != null){
							SysTaskTrigger model = new SysTaskTrigger();
							model.setId(triggerId);
							model.setPreviousDt(context.getPreviousFireTime());
							model.setNextDt(context.getNextFireTime());
							model.setFireDt(context.getFireTime());
							model.setScheduledFireDt(context.getScheduledFireTime());
							model.setStatusCode("completed");
							model.setCompleteDt(new Date());
							sysTaskTriggerService.update(model );
							Long  fireId = map.getLongValue("fireId");
							SysTaskFire fire = new SysTaskFire();
							fire.setId(fireId);
							fire.setTaskId(taskId);
							fire.setTriggerId(triggerId);
							fire.setPreviousDt(context.getPreviousFireTime());
							fire.setNextDt(context.getNextFireTime());
							fire.setFireDt(context.getFireTime());
							fire.setScheduledFireDt(context.getScheduledFireTime());
							if(context.getResult()!=null){
								fire.setResponseInfo(JSON.toJSONString(context.getResult()));
							}
							fire.setRunTime(context.getJobRunTime());
							fire.setCompleteDt(new Date());
							fire.setStatusCode("completed");
							sysTaskFireService.update(fire );
						}
						
					}
				}
				
				@Override
				public String getName() {
					return "task trigger listener";
				}
			});
		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		
	}
	
}